home *** CD-ROM | disk | FTP | other *** search
/ C/C++ Users Group Library 1996 July / C-C++ Users Group Library July 1996.iso / vol_100 / 198_02 / isearch.c < prev    next >
C/C++ Source or Header  |  1990-01-21  |  19KB  |  509 lines

  1. /*
  2.  * The functions in this file implement commands that perform incremental
  3.  * searches in the forward and backward directions.  This "ISearch" command
  4.  * is intended to emulate the same command from the original EMACS 
  5.  * implementation (ITS).  Contains references to routines internal to
  6.  * SEARCH.C.
  7.  *
  8.  * REVISION HISTORY:
  9.  *
  10.  *    D. R. Banks 9-May-86
  11.  *    - added ITS EMACSlike ISearch
  12.  *
  13.  *    John M. Gamble 5-Oct-86
  14.  *    - Made iterative search use search.c's scanner() routine.
  15.  *      This allowed the elimination of bakscan().
  16.  *    - Put isearch constants into estruct.h
  17.  *    - Eliminated the passing of 'status' to scanmore() and
  18.  *      checknext(), since there were no circumstances where
  19.  *      it ever equalled FALSE.
  20.  */
  21.  
  22. #include        <stdio.h>
  23. #include    "estruct.h"
  24. #include        "edef.h"
  25.  
  26. #if    ISRCH
  27.  
  28. extern int scanner();            /* Handy search routine */
  29. extern int eq();            /* Compare chars, match case */
  30.  
  31. /* A couple of "own" variables for re-eat */
  32.  
  33. int    (*saved_get_char)();        /* Get character routine */
  34. int    eaten_char = -1;        /* Re-eaten char */
  35.  
  36. /* A couple more "own" variables for the command string */
  37.  
  38. int    cmd_buff[CMDBUFLEN];        /* Save the command args here */
  39. int    cmd_offset;            /* Current offset into command buff */
  40. int    cmd_reexecute = -1;        /* > 0 if re-executing command */
  41.  
  42.  
  43. /*
  44.  * Subroutine to do incremental reverse search.  It actually uses the
  45.  * same code as the normal incremental search, as both can go both ways.
  46.  */
  47.  
  48. int risearch(f, n)
  49. {
  50.     LINE *curline;            /* Current line on entry          */
  51.     int  curoff;            /* Current offset on entry          */
  52.  
  53.     /* remember the initial . on entry: */
  54.  
  55.     curline = curwp->w_dotp;        /* Save the current line pointer      */
  56.     curoff  = curwp->w_doto;        /* Save the current offset          */
  57.  
  58.     /* Make sure the search doesn't match where we already are:              */
  59.  
  60.     backchar(TRUE, 1);            /* Back up a character              */
  61.  
  62.     if (!(isearch(f, -n)))        /* Call ISearch backwards          */
  63.     {                    /* If error in search:              */
  64.     curwp->w_dotp = curline;    /* Reset the line pointer          */
  65.     curwp->w_doto = curoff;        /*  and the offset to original value  */
  66.     curwp->w_flag |= WFMOVE;    /* Say we've moved              */
  67.     update(FALSE);            /* And force an update              */
  68.     mlwrite ("[search failed]");    /* Say we died                  */
  69.     } else mlerase ();            /* If happy, just erase the cmd line  */
  70. }
  71.  
  72. /* Again, but for the forward direction */
  73.  
  74. int fisearch(f, n)
  75. {
  76.     LINE *curline;            /* Current line on entry          */
  77.     int  curoff;            /* Current offset on entry          */
  78.  
  79.     /* remember the initial . on entry: */
  80.  
  81.     curline = curwp->w_dotp;        /* Save the current line pointer      */
  82.     curoff  = curwp->w_doto;        /* Save the current offset          */
  83.  
  84.     /* do the search */
  85.  
  86.     if (!(isearch(f, n)))        /* Call ISearch forwards          */
  87.     {                    /* If error in search:              */
  88.     curwp->w_dotp = curline;    /* Reset the line pointer          */
  89.     curwp->w_doto = curoff;        /*  and the offset to original value  */
  90.     curwp->w_flag |= WFMOVE;    /* Say we've moved              */
  91.     update(FALSE);            /* And force an update              */
  92.     mlwrite ("[search failed]");    /* Say we died                  */
  93.     } else mlerase ();            /* If happy, just erase the cmd line  */
  94. }
  95.  
  96. /*
  97.  * Subroutine to do an incremental search.  In general, this works similarly
  98.  * to the older micro-emacs search function, except that the search happens
  99.  * as each character is typed, with the screen and cursor updated with each
  100.  * new search character.
  101.  *
  102.  * While searching forward, each successive character will leave the cursor
  103.  * at the end of the entire matched string.  Typing a Control-S or Control-X
  104.  * will cause the next occurrence of the string to be searched for (where the
  105.  * next occurrence does NOT overlap the current occurrence).  A Control-R will
  106.  * change to a backwards search, META will terminate the search and Control-G
  107.  * will abort the search.  Rubout will back up to the previous match of the
  108.  * string, or if the starting point is reached first, it will delete the
  109.  * last character from the search string.
  110.  *
  111.  * While searching backward, each successive character will leave the cursor
  112.  * at the beginning of the matched string.  Typing a Control-R will search
  113.  * backward for the next occurrence of the string.  Control-S or Control-X
  114.  * will revert the search to the forward direction.  In general, the reverse
  115.  * incremental search is just like the forward incremental search inverted.
  116.  *
  117.  * In all cases, if the search fails, the user will be feeped, and the search
  118.  * will stall until the pattern string is edited back into something that
  119.  * exists (or until the search is aborted).
  120.  */
  121.  
  122. isearch(f, n)
  123. {
  124.     int            status;        /* Search status */
  125.     int            col;        /* prompt column */
  126.     register int    cpos;        /* character number in search string  */
  127.     register int    c;        /* current input character */
  128.     register int    expc;        /* function expanded input char          */
  129.     char        pat_save[NPAT];    /* Saved copy of the old pattern str  */
  130.     LINE        *curline;    /* Current line on entry          */
  131.     int            curoff;        /* Current offset on entry          */
  132.     int            init_direction;    /* The initial search direction          */
  133.  
  134.     /* Initialize starting conditions */
  135.  
  136.     cmd_reexecute = -1;        /* We're not re-executing (yet?)      */
  137.     cmd_offset = 0;            /* Start at the beginning of the buff */
  138.     cmd_buff[0] = '\0';        /* Init the command buffer          */
  139.     bytecopy (pat_save, pat, NPAT-1);    /* Save the old pattern string          */
  140.     curline = curwp->w_dotp;        /* Save the current line pointer      */
  141.     curoff  = curwp->w_doto;        /* Save the current offset          */
  142.     init_direction = n;            /* Save the initial search direction  */
  143.  
  144.     /* This is a good place to start a re-execution: */
  145.  
  146. start_over:
  147.  
  148.     /* ask the user for the text of a pattern */
  149.     col = promptpattern("ISearch: ");        /* Prompt, remember the col   */
  150.  
  151.     cpos = 0;                    /* Start afresh              */
  152.     status = TRUE;                /* Assume everything's cool   */
  153.  
  154.     /*
  155.        Get the first character in the pattern.  If we get an initial Control-S
  156.        or Control-R, re-use the old search string and find the first occurrence
  157.      */
  158.  
  159.     c = ectoc(expc = get_char());        /* Get the first character    */
  160.     if ((c == IS_FORWARD) ||
  161.         (c == IS_REVERSE) ||
  162.         (c == IS_VMSFORW))            /* Reuse old search string?   */
  163.     {
  164.         for (cpos = 0; pat[cpos] != 0; cpos++)    /* Yup, find the length          */
  165.             col = echochar(pat[cpos],col);    /*  and re-echo the string    */
  166.     if (c == IS_REVERSE) {            /* forward search?          */
  167.         n = -1;                /* No, search in reverse      */
  168.         backchar (TRUE, 1);            /* Be defensive about EOB     */
  169.     } else
  170.         n = 1;                /* Yes, search forward          */
  171.     status = scanmore(pat, n);        /* Do the search          */
  172.     c = ectoc(expc = get_char());        /* Get another character      */
  173.     }
  174.  
  175.     /* Top of the per character loop */
  176.             
  177.     for (;;)                    /* ISearch per character loop */
  178.     {
  179.     /* Check for special characters first: */
  180.     /* Most cases here change the search */
  181.  
  182.     if (expc == metac)            /* Want to quit searching?    */
  183.         return (TRUE);            /* Quit searching now          */
  184.  
  185.     switch (c)                /* dispatch on the input char */
  186.     {
  187.       case IS_ABORT:            /* If abort search request    */
  188.         return(FALSE);            /* Quit searching again          */
  189.  
  190.       case IS_REVERSE:            /* If backward search          */
  191.       case IS_FORWARD:            /* If forward search          */
  192.       case IS_VMSFORW:            /*  of either flavor          */
  193.         if (c == IS_REVERSE)        /* If reverse search          */
  194.         n = -1;                /* Set the reverse direction  */
  195.         else                /* Otherwise,               */
  196.         n = 1;                /*  go forward              */
  197.         status = scanmore(pat, n);        /* Start the search again     */
  198.         c = ectoc(expc = get_char());    /* Get the next char          */
  199.         continue;                /* Go continue with the search*/
  200.  
  201.       case IS_NEWLINE:            /* Carriage return          */
  202.         c = '\n';                /* Make it a new line          */
  203.         break;                /* Make sure we use it          */
  204.  
  205.       case IS_QUOTE:            /* Quote character          */
  206.